home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 12 - 1996 / 12.11 Nov 96 / Navigator Plugin Code / QuickTest.cpp < prev    next >
Encoding:
Text File  |  1996-06-17  |  18.0 KB  |  595 lines  |  [TEXT/MMCC]

  1. // QuickTest.cp                 Based on npshell.cp by NetScape Communications
  2. // by Keith McGlauflin            Portions copyright 1996 Netscape Communications
  3. //
  4. // This Netscape Navigator plugin displays an indicator strip based on the
  5. // contents of the .test file referenced in the HTML file.  Controls are
  6. // displayed to increase and decrease the indicator's level.
  7.  
  8. #ifndef _NPAPI_H_
  9. #include "npapi.h"                    // Include Netscape's header file
  10. #endif
  11.  
  12. #define    kMax    20                    // Maximum indicator value
  13. #define    kMin    1                    // Minimum indicator value
  14. #define kDecrease    "\pDecrease"    // Decrease button text
  15. #define kIncrease    "\pIncrease"    // Increase button text
  16. #define kBufferSize    1                // Size of the read buffer in bytes
  17.  
  18. // Plugin Instance Data
  19.  
  20. typedef struct _PluginInstance        // Data structure to hold all our variable for
  21. {                                    // This plug-in instance
  22.     NPWindow*        fWindow;        // Netscape Plugin Window record
  23.     uint16            fMode;            // Plugin's mode (Full screen, embedded, or background)
  24.     Boolean         amBusy;            // Are we loading data?
  25.     Ptr                data;            // Pointer to our data read from the .test file
  26.     int                datalength;        // Length of the data in Ptr
  27.     Byte            min;            // Indictator's minimum value
  28.     Byte            max;            // Indictator's maximum value
  29.     Byte            current;        // Indictator's current value
  30.     ControlHandle    decControl;        // Handle to the Decrement control
  31.     ControlHandle    incControl;        // Handle to the Increment control
  32. } PluginInstance;
  33.  
  34. // Our plugin's globals:
  35.  
  36. CGrafPort gSavePort;    // Saved Port setting
  37. CGrafPtr gOldPort;        // Original Port settings
  38. short     gRFRN;            // Resource fork reference number for this plugin's resource fork
  39. Handle     gonPict;        // Handle to the indicator's ON pict
  40. Handle     goffPict;        // Handle to the indicator's OFF pict
  41.  
  42. // Prototype functions:
  43.  
  44. Boolean SavePort( NPWindow *window );
  45. void     RestorePort( NPWindow *window );
  46. void     DrawContents( PluginInstance *This );
  47. void    HandleContents( PluginInstance *This, Point where, WindowPtr theWindow );
  48. void    AddControls( PluginInstance *This );
  49. void    UpdateCntrls( NPWindow *window );
  50. void     GetData( PluginInstance *This, unsigned long len, void *buffer );
  51. void    SetValues( PluginInstance *This );
  52. void     SetDefaults( PluginInstance *This );
  53. int        GetValue( Ptr bufferstart );
  54.  
  55. // NPP_Initialize: (from npshell.cp)  This procedure sets the clip region for our
  56. // gSavePort global, creates an FSSpec for our plugin, opens the resource fork
  57. // for our plugin, creates the gonPict and goffPict ControlHandles, and returns
  58. // NPERR_NO_ERROR.
  59.  
  60. NPError NPP_Initialize(void)
  61. {
  62.     gSavePort.clipRgn = ::NewRgn();
  63.                                                                 
  64.     gRFRN = CurResFile();                // Get the plug-in's resource file
  65.     if ( ResError( ) == noErr )
  66.         {
  67.         gonPict = GetResource( 'PICT', 3000 );        // Get the ON pict
  68.         goffPict = GetResource( 'PICT', 3001 );        // Get the OFF pict
  69.         }
  70.  
  71.     DetachResource( gonPict );
  72.     DetachResource( goffPict );
  73.     return NPERR_NO_ERROR;
  74. }
  75.  
  76.  
  77. // NPP_Shutdown: (from npshell.cp)  This procedure disposes of our clip region in 
  78. // gSavePort and releases the indicator's ON and OFF pict handles.
  79.  
  80. void NPP_Shutdown(void )
  81. {
  82.     if (gSavePort.clipRgn)
  83.         ::DisposeRgn(gSavePort.clipRgn);
  84.         
  85.     ReleaseResource( gonPict );                    // Release the on Pict's resource
  86.     ReleaseResource( goffPict );                // Release the off Pict's resource
  87. }
  88.  
  89.  
  90. // NPP_New: (from noshell.cp)  This routine creates a new plugin instance.  First the
  91. // plugin validates the instance we received from Navigator, then it allocates enough
  92. // memory to hold the PluginInstance data structure.  Finally, the plugin sets all
  93. // the variables of our instance to their initial state.
  94.  
  95. NPError NPP_New(NPMIMEType pluginType,
  96.                 NPP instance,
  97.                 uint16 mode,
  98.                 int16 argc,
  99.                 char* argn[],
  100.                 char* argv[],
  101.                 NPSavedData* saved)
  102. {
  103.     if (instance == NULL)                        // Check for invalid plugin instance
  104.         return NPERR_INVALID_INSTANCE_ERROR;
  105.         
  106.         
  107.     instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
  108.     PluginInstance* This = (PluginInstance*) instance->pdata;
  109.     if (This != NULL)
  110.     {                                    // Initialize our plugin instance's variables
  111.         This->fWindow = NULL;                    // No window assigned yet
  112.         This->amBusy = FALSE;                    // Not currently loading data 
  113.         This->data = NULL;                        // Data pointer is NULL
  114.         This->datalength =0;                    // Length of data is zero
  115.         This->min = 0;                            // Min, max and current are set
  116.         This->max = 0;                            // to zero
  117.         This->current =0;
  118.         This->decControl = NULL;                // ControlHandles set to NULL
  119.         This->incControl = NULL;
  120.         
  121.         return NPERR_NO_ERROR;
  122.     }
  123.         else
  124.             return NPERR_OUT_OF_MEMORY_ERROR;    // Couldn't get enough memory
  125. }
  126.  
  127.  
  128.  
  129. // NPP_Destroy: ( from npshell.cp )  This procedure destroys a PluginInstance.  First
  130. // the data pointer's memory is freed, then the controls are destroyed, and finally 
  131. // the instance itself is freed and set to zero (so that it won't be errantly used again).
  132.  
  133. NPError NPP_Destroy(NPP instance, NPSavedData** save)
  134. {
  135.     if (instance == NULL)                        // Check for invalid plugin instance
  136.         return NPERR_INVALID_INSTANCE_ERROR;
  137.  
  138.     PluginInstance* This = (PluginInstance*) instance->pdata;
  139.  
  140.     if (This != NULL)
  141.     {
  142.         if (This->data)
  143.             NPN_MemFree(This->data);            // Free up data pointer
  144.         
  145.         if ( This->decControl != NULL )            // Destroy the controls
  146.             DisposeControl( This->decControl );
  147.         if ( This->incControl != NULL )
  148.             DisposeControl( This->incControl );
  149.  
  150.         NPN_MemFree(instance->pdata);            // Free instance data
  151.         instance->pdata = NULL;                    // Set instance to NULL
  152.     }
  153.  
  154.     return NPERR_NO_ERROR;
  155. }
  156.  
  157.  
  158.  
  159.  
  160. // NPP_SetWindow: ( from npshell.cp )  This procedure sets our PluginInstance's window
  161. // to the window passed as a parameter in this procedure.
  162.  
  163. NPError NPP_SetWindow(NPP instance, NPWindow* window)
  164. {
  165.     if (instance == NULL)
  166.         return NPERR_INVALID_INSTANCE_ERROR;
  167.  
  168.     PluginInstance* This = (PluginInstance*) instance->pdata;
  169.  
  170.     This->fWindow = window;            // Set this instance window to the NPwindow
  171.  
  172.     return NPERR_NO_ERROR;
  173. }
  174.  
  175.  
  176.  
  177.  
  178. // NPP_NewStream: (from npshell.cp)  Sets the amBusy boolan to true, indicating that
  179. // we are ready to load data from the .test file.
  180.  
  181. NPError NPP_NewStream(NPP instance,
  182.                             NPMIMEType type,
  183.                             NPStream *stream, 
  184.                             NPBool seekable,
  185.                             uint16 *stype)
  186. {
  187.     if (instance == NULL)
  188.         return NPERR_INVALID_INSTANCE_ERROR;
  189.     PluginInstance* This = (PluginInstance*) instance->pdata;
  190.  
  191.     This->amBusy = TRUE;            // Loading data...
  192.  
  193.     return NPERR_NO_ERROR;
  194. }
  195.  
  196.  
  197.  
  198. // NPP_WriteReady: ( from npshell.cp )  Returns the value of our read buffer.
  199. // (Navigator will be doing the writing, our plugin will be reading.)
  200.  
  201. int32 NPP_WriteReady(NPP instance, NPStream *stream)
  202. {
  203.     return kBufferSize;                // Return our buffersize
  204. }
  205.  
  206.  
  207.  
  208.  
  209. // NPP_Write: ( from npshell.cp )  Loads the data from the .test file into the 
  210. // PluginInstance.
  211.  
  212. int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
  213. {
  214.     if (instance == NULL)                        // Check for invalid plugin instance
  215.         return NPERR_INVALID_INSTANCE_ERROR;    
  216.         
  217.     PluginInstance* This = (PluginInstance*) instance->pdata;
  218.  
  219.     if (This != NULL)
  220.         GetData(This, len, buffer);                // Load the .test file's data into 
  221.                                                 // This->data
  222.     return 0;
  223. }
  224.  
  225.  
  226.  
  227.  
  228. // NPP_DestroyStream:  ( from npshell.cp )  When finished reading data, the plugin will
  229. // set amBusy to false, set the min, max and current values of our PluginInstance,
  230. // draw the controls, and draw the indicator.
  231.  
  232. NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
  233. {
  234.     if (instance == NULL)                        // Check for invalid plugin instance
  235.         return NPERR_INVALID_INSTANCE_ERROR;
  236.         
  237.     PluginInstance* This = (PluginInstance*) instance->pdata;
  238.  
  239.     This->amBusy = FALSE;                        // Finished loading...
  240.     
  241.     if (SavePort(This->fWindow))                // Save the current GrafPort
  242.     {    
  243.         SetValues( This );                        // Set min, max and current
  244.         AddControls( This );                    // Draw the controls
  245.         DrawContents(This);                        // Draw the indicator
  246.         RestorePort(This->fWindow);                // Restore the old GrafPort
  247.     }
  248.  
  249.     return NPERR_NO_ERROR;
  250. }
  251.  
  252.  
  253.  
  254. // NPP_StreamAsFile: ( from npshell.cp )
  255.  
  256. void NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
  257. {
  258. // QuickTest doesn't suppose loading files
  259. }
  260.  
  261.  
  262.  
  263. // NPP_HandleEvent: ( from npshell.cp )  Takes a pointer to an event, casts it to
  264. // an EventRecord* and handles the event.  This plugin only handles update and
  265. // mousedown events.
  266.  
  267. int16 NPP_HandleEvent(NPP instance, void* event)
  268. {
  269.     Boolean eventHandled = false;    // Has the event been processed?
  270.     WindowPtr theWindow;            // Window where mouse was pressed
  271.     short wherePressed;                // Coordinates where mouse was pressed
  272.     EventRecord    *ev;                // Event record for this event
  273.     NP_Port    *port;                    // The window for mouse click
  274.     
  275.     if (instance == NULL)            // Check for invalid plugin instance
  276.         return eventHandled;
  277.         
  278.     PluginInstance* This = (PluginInstance*) instance->pdata;
  279.     if (This != NULL && event != NULL)
  280.     {
  281.         ev = (EventRecord*) event;        // Convert the event to an EventRecord
  282.         switch (ev->what)                // Get the type of event
  283.         {
  284.             case updateEvt:                            // Update event:
  285.                 if( SavePort( This->fWindow ) )        // Save the current GrafPort
  286.                 {
  287.                     DrawContents(This);                // Draw the contents
  288.                     UpdateCntrls( This->fWindow );    // Update the controls
  289.                     RestorePort( This->fWindow );    // Restore the old GrafPort
  290.                 }
  291.                 eventHandled = true;                // Event was processed
  292.                 break;
  293.                 
  294.             case mouseDown:                            // Mouse down:
  295.                 port = (NP_Port*) This->fWindow->window;    // Get the GrafPort from the
  296.                 theWindow = ( WindowPtr ) port->port;        // fWindow data structure
  297.                 if ( theWindow != FrontWindow() )            // If window isn't front window
  298.                     BringToFront( theWindow );                // bring it to the front.
  299.                         else
  300.                         {
  301.                             wherePressed = FindWindow( ev->where, &theWindow );
  302.                                                     // Find where mouse down
  303.                             switch ( wherePressed )    // If mouse press down in...
  304.                             {
  305.                                 case inContent:        // ...content...
  306.                                     if( SavePort( This->fWindow ) )    // Save current GrafPort
  307.                                     {
  308.                                         HandleContents( This, ev->where, theWindow );
  309.                                                      // Handle the mouse down event
  310.                                         RestorePort( This->fWindow );
  311.                                                     // Restore the old GrafPort
  312.                                     }
  313.                                     break;
  314.                             }
  315.                         }
  316.                 break;
  317.                 
  318.             default:
  319.                 break;
  320.         }
  321.             
  322.     }
  323.     
  324.     return eventHandled;    // Let Navigator know if we processed the event
  325. }
  326.  
  327.  
  328.  
  329. // NPP_Print: ( from npshell.cp )  For brevity this procedure isn't implemented.
  330. // The code in this procedure does the minimal processing required to make printing
  331. // work (note that the plugin's indicator and controls are not printed - see the
  332. // examples in the Plugin SDK for information on printing within plugins).
  333.  
  334. void NPP_Print(NPP instance, NPPrint* printInfo)
  335. {
  336.     if (instance != NULL)
  337.     {
  338.         if (printInfo->mode == NP_FULL)        // in fullscreen mode we don't do anything
  339.                                             // for printing.
  340.             printInfo->print.fullPrint.pluginPrinted = false;
  341.     }
  342. }
  343.  
  344.  
  345. // NPP_URLNotify: Not implemented
  346.  
  347. void    NPP_URLNotify(NPP instance, const char* url,NPReason reason, void* notifyData)
  348. {
  349. // QuickTest doesn't implement this method
  350. }
  351.                             
  352.  
  353. // NPP_GetJavaClass: Not Implemented (NOTE: this gives a warning during Make)
  354.                             
  355. jref    NPP_GetJavaClass(void)
  356. {
  357. // QuickTest doesn't implement this method    
  358. }
  359.  
  360. // SavePort: Since Mac plugins share the drawing environment with Navigator we MUST
  361. // save the current GrafPort settings.  This subroutine saves the current port's
  362. // clipping rectangle.  Save other port settings before you change them.
  363.  
  364. Boolean SavePort(NPWindow *window)
  365. {
  366.     Rect clipRect;
  367.     NP_Port* port;
  368.     if (window == NULL)
  369.         return FALSE;
  370.     
  371.     port = (NP_Port*) window->window;
  372.     if (window->clipRect.left < window->clipRect.right)
  373.     {
  374.     // Preserve the old port
  375.         ::GetPort((GrafPtr*)&gOldPort);
  376.         ::SetPort((GrafPtr)port->port);
  377.         
  378.     // Preserve the old drawing environment
  379.         gSavePort.portRect = port->port->portRect;
  380.         ::GetClip(gSavePort.clipRgn);
  381.         
  382.     // Setup our drawing environment
  383.     
  384.         clipRect.top = window->clipRect.top + port->porty;
  385.         clipRect.left = window->clipRect.left + port->portx;
  386.         clipRect.bottom = window->clipRect.bottom + port->porty;
  387.         clipRect.right = window->clipRect.right + port->portx;
  388.         ::SetOrigin(port->portx,port->porty);
  389.         ::ClipRect(&clipRect);
  390.         clipRect.top = clipRect.left = 0;
  391.         return TRUE;
  392.     }
  393.     else
  394.         return FALSE;
  395. }
  396.  
  397.  
  398.  
  399. // RestorePort: restore the old port settings so Navigator has the same GrafPort setting
  400.  
  401. void RestorePort(NPWindow *window)
  402. {
  403.     NP_Port* port;
  404.     CGrafPtr myPort;
  405.     
  406.     port = (NP_Port*) window->window;
  407.     ::SetOrigin(gSavePort.portRect.left, gSavePort.portRect.top);
  408.     ::SetClip(gSavePort.clipRgn);
  409.  
  410.     ::GetPort((GrafPtr*)&myPort);
  411.     ::SetPort((GrafPtr)gOldPort);
  412. }
  413.  
  414.  
  415.  
  416. // DrawContents: draw the indicator.  Indicator is made up of on and off Picts which
  417. // must be loaded from the plugin's resource fork.
  418.  
  419. void DrawContents(PluginInstance *This)
  420. {
  421.     Rect    drawRect;            // Drawing rectangle
  422.     short    loop;                // Loop to process indicator
  423.     
  424.         drawRect.top = 0;                            // Set the initial draw rectangle
  425.         drawRect.bottom = 34;
  426.         drawRect.left = 0;
  427.         drawRect.right = 17;
  428.         
  429.         for ( loop = This->min; loop <= This->current; loop++ ) // Draw the ON picts for
  430.         {                                                        // the indicator
  431.             ::DrawPicture( (PicHandle) gonPict, &drawRect );    
  432.             drawRect.left += 23;                                // Move the draw rectangle
  433.             drawRect.right = drawRect.left + 17;                // to the right
  434.         }
  435.                 
  436.         for ( loop = This->current+1; loop <= This->max; loop++ )     // Draw OFF picts for
  437.         {                                                            // the indicator
  438.             ::DrawPicture( (PicHandle) goffPict, &drawRect );
  439.             drawRect.left += 23;                                // Move the draw rectangle
  440.             drawRect.right = drawRect.left + 17;                // to the right
  441.         }
  442.                 
  443. }
  444.  
  445.  
  446. // HandleContents: process mouse clicks in the contents of the window.  Track clicks
  447. // in the controls and process those clicks.
  448.  
  449. void HandleContents( PluginInstance *This, Point where, WindowPtr theWindow )
  450. {
  451.     int part, thePart;            // part mouse down occurred
  452.     ControlHandle theControl;    // Control mouse was pressed in
  453.     Str255    theTitle;            // Control's title
  454.     
  455.     GlobalToLocal( &where );    // Convert coordinates
  456.     part = FindControl( where, theWindow, &theControl );    // Find control were mouse
  457.                                                             // down occurred
  458.     if ( theControl != NULL )                                // If control valid
  459.     {
  460.         thePart = TrackControl( theControl, where, nil );    // Track the press
  461.         if ( thePart == inButton )                            // If release in button
  462.         {
  463.             ::GetControlTitle( theControl, theTitle );        // Get the title of the control
  464.             if ( EqualString( theTitle, kDecrease, false, false ) )
  465.             {                                                // If decrease title...
  466.                 This->current--;                            // Decrease indicator's current 
  467.                                                             // value
  468.                 if ( This->current < This->min )            // Make sure current >= min
  469.                 {
  470.                     This->current = This->min;                // Make current = min
  471.                     ::SysBeep( 10 );
  472.                 }    
  473.                 DrawContents( This );                        // Draw the contents
  474.             }
  475.             if ( EqualString( theTitle, kIncrease, false, false ) )
  476.             {                                                // If increase title...
  477.                 This->current++;                            // Increase indicator;s current
  478.                                                             // value
  479.                 if ( This->current > This->max )            // Make sure current <= max
  480.                 {
  481.                     This->current = This->max;                // Make current = max
  482.                     ::SysBeep(10);
  483.                 }        
  484.                 DrawContents( This );                        // Draw the contents
  485.             }
  486.         }
  487.     }
  488. }
  489.  
  490.  
  491. // UpdateCntrls: updates the controls for the window.
  492.  
  493. void    UpdateCntrls( NPWindow *window )
  494. {
  495.     WindowPtr    theWindow;        // Window pointer for window which contains controls
  496.     NP_Port        *port;            // NP_port which points to GrafPort
  497.  
  498.     port = ( NP_Port* ) window->window;        // Convert fWindow
  499.     theWindow = ( WindowPtr ) port->port;    // to a WindowPtr
  500.  
  501.     UpdateControls( theWindow, theWindow->visRgn );        // Update the window's controls
  502. }
  503.  
  504.  
  505. // GetData: Get the data out of the buffer and put it into the data pointer of
  506. // our plugin instance.
  507.  
  508. void GetData( PluginInstance *This, unsigned long len, void *buffer )
  509. {
  510.     char *newText;
  511.     long offset;
  512.     
  513.     if (This->data == NULL)                      // No data loaded yet
  514.     {
  515.         newText = (char*) NPN_MemAlloc(len);    // Allocate newText
  516.         This->datalength = 0;                    // Set length of data
  517.         offset = 0;                                // Set initial offset
  518.     }
  519.     else                                                        // We've loaded data
  520.     {
  521.         newText = (char*) NPN_MemAlloc(This->datalength+len);
  522.         BlockMove(This->data, newText, This->datalength);
  523.         NPN_MemFree(This->data);
  524.         offset = This->datalength;
  525.     }
  526.     BlockMove(buffer, newText+This->datalength, len);    // Move buffer data 
  527.     This->data = newText;                                // info data
  528.     This->datalength += len;                            // and set the length
  529. }
  530.  
  531.  
  532. // SetValues: convert data to min, max and current values.  If values are out
  533. // of bounds then set min, max and current to default values.
  534.  
  535. void SetValues( PluginInstance *This )
  536. {
  537.     This->min = GetValue( This->data );                    // Set min
  538.     This->max = GetValue( ( This->data ) + 7 );            // Set max
  539.     This->current = GetValue( ( This-> data ) + 14 );    // set current
  540.  
  541.     if ( ( This->min > This->current ) || ( This->max < This->current ) )
  542.         SetDefaults( This );            // Use default if current too low or too high
  543.     
  544.     if ( ( This->min < kMin ) || ( This->min > kMax ) )
  545.         SetDefaults( This );            // Use default if min too low or too high
  546.     
  547.     if ( ( This->max < kMin ) || ( This->max > kMax ) )
  548.         SetDefaults( This );            // Use default if max too low or too high
  549.     
  550.     if ( This->max < This->min )        
  551.         SetDefaults( This );            // Use default if min greater than max
  552. }
  553.  
  554.  
  555. // SetDefaults: If min, max or current out of range set all three to defaults
  556.  
  557. void SetDefaults( PluginInstance *This )
  558. {
  559.     This->min = kMin;
  560.     This->max = kMax;
  561.     This->current = kMin;
  562. }
  563.  
  564.  
  565. // GetValues: read three bytes starting at bufferstart+4 ( to skip over the
  566. // min=, max=, or cur= ) and convert it to an integer.
  567.  
  568. int GetValue( Ptr    bufferstart )
  569. {
  570.     int value = 0;
  571.  
  572.     bufferstart = bufferstart + 4;
  573.     value = ( ( *(bufferstart) - 48 ) * 100 ) + 
  574.         ( ( *(bufferstart + 1 ) - 48 ) * 10 ) + ( *(bufferstart + 2 ) - 48 );
  575.     return value;
  576. }
  577.  
  578.  
  579. // AddControls: add the controls for increase and decrease to the window
  580.  
  581. void AddControls( PluginInstance *This )
  582. {
  583.     Rect        drawRect;
  584.     WindowPtr    theWindow;
  585.     NP_Port        *port;
  586.  
  587.     port = (NP_Port*) This->fWindow->window;    // Convert the fWindow
  588.     theWindow = ( WindowPtr ) port->port;        // to a window pointer
  589.     
  590.     SetRect( &drawRect, 10, 46, 100, 71 );        // Rect for the decrement control
  591.     This->decControl = NewControl( theWindow, &drawRect, "\pDecrease", true, 0, 0, 1, pushButProc, 0);
  592.         
  593.     SetRect( &drawRect, 120, 46, 210, 71 );        // Rect for the increment control
  594.     This->incControl = NewControl( theWindow, &drawRect, "\pIncrease", true, 0, 0, 1, pushButProc, 1);
  595. }